iT邦幫忙

2026 iThome 鐵人賽

DAY 16
0
IT Operation

地端機房的三十天維運:開源服務封裝、GPU 節點守護與可稽核的變更管理系列 第 16 篇

Day 16|Proxmox VE 備份與還原:HDP for Business Beta 的排程、保留與還原演練

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20260930/20141816ddumKYNtq2.png

「備份的證據除了看到管理介面上的綠燈,更重要的是還原成功的那一刻。」


備份的證據是還原

在 [Day 15] 中,我把核心 VM 遷移至 NAS 的 NFS 共享儲存,並透過 HA 故障轉移演練,測試出節點斷電後,VM 在另一台主機重啟前存在 205.8 秒 的寫入空窗。

但必須認清一個現實:HA(高可用性)處理的是節點硬體損毀,不處理磁碟內容損毀。

當 VM 內部的資料遭到勒索軟體加密、被工程師誤刪、或因錯誤的組態發布搞爛系統時,HA 只會忠實且迅速地在另一台節點上,把那個「已經壞掉的磁碟」重新跑起來。這一層災難必須仰賴備份,而備份只有在還原成功的那一刻,才算真正存在。

這個環節採用最近較熱門且新的 HDP (Hybrid Backup Center) for Business Beta,關鍵理由有三:

  1. 無代理程式(Agentless): 直接透過 SSH 支援 Proxmox VE,節點端不需要安裝任何 Agent。
  2. 底層不可變(Immutable): 備份儲存庫建立於 QuTS hero 的 WORM 資料夾上。
  3. 開機影片驗證: 每次備份完成會自動啟動臨時 VM 側錄開機畫面,作為稽核證據。

這篇文章聚焦專注三個問題:這個場域備什麼、原則表每個數字的依據、以及還原演練如何精確量化為 RTO 與 RPO。 文中所有資料,皆為本場域實測獲得。

📦 本篇實作程式碼: pve-backup-drill
內含兩支測試腳本與演練紀錄範本。腳本不依賴 HDP,是通用的,適合 IT 與維運人員應用在各種資訊環境中使用,無論底層採用 PBS、Veeam 還是自建 restic 皆可通用。


一、這個場域備什麼 ?

備份清單從 Day 15 的資源清單出發。在實際將 PVE 叢集接入 HDP 後,發現了預期之外的落差:

保護對象 虛擬磁碟所在 HDP 備份支援 現況說明與處理策略
叢集上的 VM NAS 的 NFS 支援 HDP 以 root 經 SSH 連上叢集,可自動列出並保護每一台 VM。
叢集上的 LXC 容器 NAS 的 NFS ❌ 無法 盤點缺口。 叢集有 5 台 VM、15 個容器,HDP 僅回報 vmCount: 5,LXC 完全不在清單內。
QDevice VM NAS 本機(Virtualization Station) 不納入 無狀態仲裁節點,故障時可於 10 分鐘內依腳本重建(見 Day 15)。
PVE 節點本身 實體節點本機 不納入 依 Day 11 基線重灌,/etc/pve 設定由叢集其餘在線節點自動同步。

盤點發現的關鍵缺口

  1. LXC 不在保護名單:
    本場域的容器負責內部 DNS 解析與過濾,雖然設定極輕量且具備組態腳本,但「無法被 HDP 保護」是既定事實。這件事必須白紙黑字寫進維運原則表,切忌給團隊「整個叢集都有備份」的錯覺。

  2. 自動保護規則(Auto-Protect)的地雷:
    HDP 提供「自動將新發現的 VM 納入預設備份原則」的功能。實測新建一台 VM,重整後確實會自動納管,對動態環境很方便。
    但它也會把不該動的正式 VM 強行排程: 在規則啟用下,場域內一台 488 GB 與一台 250 GB 的正式 VM 被自動排進每天 09:00 的預設原則。當我想停用該規則時,API 對 enabled: false 回傳 HTTP 200,後台狀態卻毫無改變。最後只能以手動方式把那幾個 Workload 逐一停用。
    維運決策: 正式環境停用全域自動保護,所有納管項目一律依原則表逐台審查加入。此外,還原演練產生的測試 VM 也會被自動納管,演練結束後務必刪除對應 Workload,避免隔天排程對已刪除的 VM 報錯。


二、備到哪:一台 NAS,正本與備份的考量

HDP for Business 的管理伺服器與備份儲存庫,與 Day 13、Day 14 的 AI 模型庫共用同一台 QuTS hero NAS(h6.0.2.3591),更關鍵的是,VM 運行中的 NFS 磁碟也在同一個儲存池(Storage Pool)。

┌────────────────────────────────────────────────────────┐
│                   單一 NAS (QuTS hero)                  │
│ ┌────────────────────────────────────────────────────┐ │
│ │               同一個實體儲存池 (Pool 1)               │ │
│ │  ┌───────────────────────┐  ┌───────────────────┐  │ │
│ │  │ VM 運行中磁碟 (NFS)    │  │ HDP 備份儲存庫    │  │ │
│ │  │ [ 正本資料 ]           │  │ [ WORM 不可變副本] │  │ │
│ │  └───────────┬───────────┘  └─────────▲─────────┘  │ │
│ └──────────────┼────────────────────────┼────────────┘ │
└────────────────┼────────────────────────┼──────────────┘
                 │ (故障/加密/誤刪)       │ (還原路徑)
                 ▼                        │
          ┌─────────────┐                 │
          │ PVE Cluster ├─────────────────┘
          └─────────────┘

風險揭露:
正本與備份在同一個儲存池,一旦實體磁碟群組(RAID)崩潰或硬體損毀,兩份資料會一起消失。
因此,本機這一份備份僅能防範三件事:客體內勒索軟體加密、人為誤刪、錯誤的程式與資料變更。
至於實體機房與硬體層級的容災,是 Day 17(NAS 快照與 3-2-1)與 Day 18(異地副本)的工作。

HDP 的底層資料流機制

  • 調度與讀取: 由 Bareos 引擎負責工作排程與虛擬磁碟區塊讀取。
  • 去重與壓縮: 底層透過 restic 進行去重與壓縮。全站台共用單一 restic 儲存庫,跨 Workload 之間的相同資料區塊只存一份。

三、原則表與每個數字的底層依據

維運團隊在面對資安與維運稽核時,最怕被問「為什麼是這個數字呢?」答不出來的數字,在稽核時會很麻煩,因此我將規格梳理成 policy.md:

項目 設定值 具體依據與設計考量
原則類型 不可變(Immutable) 建立後無法改回一般原則,必須一開始決定。啟用底層 WORM 機制。
排程頻率 每日 01:30(首次完整,其後增量) 避開 NAS 自身維護作業:01:00 釋放快取、02:00 qfstrim、03:00 惡意程式掃描與 vs_refresh。01:30 夾在中間,32 GB 的 VM 增量備份不到 1 分鐘即可完成。
保留週期 30 天(每日一版,共 30 版) 不可變原則僅支援依「天數」保留,設定「版本數」會被系統靜默忽略。30 天涵蓋一個月的變更單回溯期(Day 26),亦涵蓋勒索軟體常見的潛伏期。覺得太多就改成10天到14天。
不可變期間 30 天(與保留相同) 每個版本寫入後強制鎖定 30 天,期間任何管理者權限皆無法刪除。天數也可以刪減改短一天的天數。
備份驗證 啟用,120 秒 每次備份後開機錄製畫面,作為 Day 27 的稽核證據。
Airgap+ ❌ 不啟用 Airgap+ 會在非備份時段將備份伺服器關機。但該 NAS 同時承載 NFS、QDevice 與模型庫,關機將直接導致 PVE 叢集全面停擺(Day 15 演練 3)。
異地副本 預留欄位 留待 Day 18 異地不可變物件儲存整合。

深度探討:本機不可變到底鎖住了什麼?

備份完成後,HDP 會將該版本新寫入的檔案設為唯讀,並將檔案的存取時間(atime)改為到期時間。

但請務必注意:不可變鎖定的範圍僅限「該版本新寫入的 pack 檔案」。 實查整個 restic 儲存庫結構:

儲存庫目錄/範圍 檔案數量 佔用空間 鎖定狀態
演練 VM 3 個版本新寫入的資料 164 個 pack 檔 2,703.9 MiB 唯讀(鎖定至 10/30)
先前其他 Workload 共用的舊資料 4,208 個 pack 檔 69,781.2 MiB 可讀寫(未鎖定)
儲存庫核心:config、keys/、舊 index 23 個檔案 約 6 MiB 可讀寫(未鎖定)

演練 VM 去重後的總佔用為 2,831.6 MiB,比新鎖定的空間多了約 128 MiB。這 128 MiB 是與先前其他工作負載共用的舊 pack,它們並不會被補鎖。更關鍵的是,restic 解鎖儲存庫必備的 config 與 keys/ 同樣保持可寫。

這代表本機不可變保護的是新增的資料區塊,而非整個儲存庫防毀。完整的防篡改防線必須仰賴 Day 18 的異地 Object Lock。


四、還原演練怎麼測量呢 ?

備份管理介面顯示綠燈,絕不代表系統能順利還原。之前的排程備份中,兩台正式 VM 在主控台回報失敗,原因在於 HDP API 連續回傳 500,備份工作根本沒能派送進 Bareos 核心。

要確認備份有效性,唯一的途徑就是實做還原,並客觀量化指標:

  • RTO(Recovery Time Objective,復原時間目標): 從觸發災難到服務完全恢復正常運作的秒數。
  • RPO(Recovery Point Objective,復原點目標): 還原後的資料時間點與災難發生當下的時間差距。

為了消除人工看錶估算的誤差,實作了兩支自動化驗證腳本:

                       [ 演練開始 (T0) ]
                               │
            ┌──────────────────┴──────────────────┐
            ▼                                     ▼
      [ 原 VM 硬關機 ]                     [ restore-drill.sh ]
      (模擬實體硬體損毀)                             │ (每 2 秒輪詢一次)
                                                  ├─ 1. VM 出現在叢集設定中
                                                  ├─ 2. VM 狀態轉為 running
                                                  ├─ 3. 網路回應 ping
                                                  ├─ 4. SSH 22 埠開放
                                                  ▼
                                      [ SSH 執行 canary.sh verify ]
                                                  │
                                                  ├─ 補寫心跳 (消弭 60s 誤差)
                                                  ├─ 尋找 >180s 之最後中斷點
                                                  ├─ 計算精確 RPO
                                                  ├─ 校驗 64MiB Payload SHA256
                                                  ▼
                                            [ 計算整體 RTO ]

1. canary.sh(部署於被保護的客體內)

  • 每分鐘寫入一筆心跳(epoch 秒數、ISO 時間、主機名稱),寫入後強制執行 fsync,確保快照前資料已確實刷入磁碟。
  • 放置一個 64 MiB 的隨機二進位檔案(payload),安裝時預先記錄 SHA256 雜湊。
  • 還原後執行 canary.sh verify:
    1. 立即補寫一筆心跳(避免等待 cron 造成最多 60 秒的 RTO 評估灌水)。
    2. 搜尋心跳紀錄中最後一個超過 180 秒的時間斷層,斷層前最後一筆心跳即為精確還原點。
    3. 比對模擬故障時間,輸出精確 RPO。
    4. 驗證 64 MiB payload 的 SHA256,確認資料無損。
    5. 輸出客體 NTP 同步狀態(關鍵除錯依據)。

2. restore-drill.sh(控制端執行)

在按下還原的瞬間同步啟動。以 2 秒為週期依序偵測五大事件:

  1. VM 出現在叢集設定中
  2. VM 進入 running 狀態
  3. VM 回應 ICMP Ping
  4. TCP 22 埠開放
  5. 成功 SSH 登入並通過 canary.sh verify

RTO 的終點是 canary 驗證通過
若採用 HDP 即時還原(開在 NAS 的 Virtualization Station),則附加 --no-pve 參數略過 PVE 前置檢查。


五、先量備份效能

演練 VM 規格:Debian 13、2 vCPU、2 GB RAM,32 GB 的 qcow2 格式虛擬磁碟置於 NFS 上,系統實體佔用約 3 GB(包含 1 GiB 隨機資料、0.9 GB 可壓縮文字與作業系統核心)。

版本 操作內容 備份類型 Bareos 讀取量 Bareos 耗時 工作總時間 去重後累計佔用
Ver 1 初始基準版本 完整 32.75 GB 5 分 06 秒(107 MB/s) 6 分 01 秒 1.68 GB
Ver 2 客體內寫入 1 GiB 隨機檔 增量 1.084 GB 14 秒 57 秒 2.76 GB
Ver 3 客體關機重開,寫入 200 MiB 增量 324.2 MB 7 秒 32 秒 2.97 GB
Ver 4 改為靜態 IP,重開機 增量 122.5 MB 6 秒 32 秒 2.97 GB

實測觀察到的三個底層關鍵

  1. 完整備份讀取的是「配置容量」而非「使用量」:
    雖然客體僅使用了 3 GB,HDP 依然讀滿了配置的 32 GB。在此網路與儲存環境下,讀取速率約每 GB 9.3 秒。這意味著場域中另一台 488 GB 的正式 VM,第一次完整備份單純讀取就要耗去約 76 分鐘。
  2. 增量備份精確傳輸變更:
    寫入 1 GiB 變更,Bareos 讀取 1.084 GB,資料增量傳輸表現優異。
  3. qcow2 關機後重開依然具備增量追蹤能力(CBT):
    HDP 仰賴 QEMU 的 dirty bitmap 追蹤變更區塊。官方 FAQ 指出 raw 與 vmdk 格式在關機後會遺失追蹤記錄,導致下次備份退化為完整備份。
    實測證實:qcow2 關機重開後,第三次備份依然維持增量備份(僅讀取 324.2 MB)。 透過 qemu-img info 檢驗虛擬磁碟,可以看到 dirty bitmap 是以 Bareos 工作名稱直接持久化在 qcow2 檔案結構內部,而 raw 映像檔則無此元數據結構。
    落地建議: 大容量 VM 強烈建議採用 qcow2 格式。若使用 raw,每次關機後的備份都將面臨數十分鐘的漫長全備份。

六、四個還原演練實測結果

演練資料彙整自 drill-log.md,時間基準採 UTC,秒數從觸發模擬故障(按下還原)起算:

演練項目 精確還原點 ping 通 ssh 開 實測 RTO 實測 RPO 演練結果與關鍵備註
1. 即時還原(DHCP) 15:05:02Z 逾時 逾時 未完成 222 s FAIL。IP 漂移,控制面失敗。
1'. 即時還原重做(靜態 IP) 15:34:02Z 113 s 115 s 118 s 97 s OK。118 秒恢復對外服務。
2. 即時還原轉為永久 15:34:02Z 不中斷 不中斷 187 s (背景) 97 s OK。轉換過程 0 秒中斷。
3. 完整還原回 NFS 叢集 15:34:02Z 568 s 568 s 569 s 784 s OK。全機回滾,抓出光碟依賴坑。
4. 還原第 1 版(最舊不可變) 14:49:01Z 527 s 529 s 530 s 4,104 s OK。證明鎖定版可還,資料點精確。

演練 1:服務起來了,但不在原本的位址

即時還原預設使用 IDE 磁碟與 VirtIO 網卡,沿用原 VM 的 MAC 位址還原最新版本。時間序如下:

[+0s]   原 VM 強制關機(模擬故障),發動即時還原
[+108s] HDP 介面回報「即時還原成功」
[+121s] 客體核心開機完畢
[+130s] sshd 服務啟動
[+132s] 客體自 DHCP 取得 IP —— 但拿到了不同的 IP 位址!

雖然 MAC、DHCP Client ID 與主機金鑰完全一致,DHCP 伺服器仍然指派了全新位址。控制腳本 restore-drill.sh 依原 IP 偵測不到回應而判定逾時。在真實災難中,這就是標準的「監控面板全是綠燈,外部連線全面中斷」。

事後透過 Console 登入客體執行 canary.sh verify:

  • 還原點為 15:05:02Z(備份開始前最後一筆心跳)。
  • RPO 為 222 秒,64 MiB payload 雜湊驗證完全正確。資料成功救回,但通訊控制宣告失敗。

問題二:硬體時鐘(RTC)快 8 小時
分析心跳紀錄時,赫然發現一筆時間戳記為 23:11:01Z,比真實世界快了整整 8 小時!
原來 Virtualization Station 將 NAS 本地時間當成 UTC 拋給客體虛擬機,導致客體開機初期使用錯誤時間寫入心跳,直到 41 秒後 NTP 校時完成才回歸正常。
由於 canary.sh verify 演算法採取「最後一個中斷點」,還原點並未失真,但斷層時間出現了偽造的 29,159 秒。這正是驗證工具必須納入 NTP 檢查的原因。

關鍵結論: 具備即時災備需求的 VM,絕對不能使用動態 DHCP,必須於作業系統層配置靜態 IP 或在路由器綁定 DHCP 靜態保留。


演練 1':改用靜態 IP 重測即時還原

在 VM 內將 cloud-init 網路設定停用(network: {config: disabled}),改以 Netplan 配置 DHCP 範圍外的固定 IP,確認重開機組態未被覆蓋後,執行 Ver 4 備份並重做演練:

  • 0 秒: 模擬斷電,送出即時還原。
  • 87 秒: HDP 回報還原成功。
  • 113 秒: 原固定 IP 恢復 ping 回應。
  • 115 秒: 22 埠開放。
  • 118 秒: SSH 自動驗證通過,還原點 15:34:02Z,RPO 97 秒,RTO 118 秒!

洞察: HDP 主控台顯示成功是在第 87 秒,但服務實際可用是在第 118 秒,兩者存在 31 秒的空窗差。唯有 end-to-end 腳本驗證,才能抓出真正的 RTO。


演練 2:轉為永久虛擬機,服務零中斷

即時還原出來的 VM 是以 FUSE 掛載備份映像檔、外掛 Overlay 層承接寫入運行。若要長期運作,必須「轉為永久」,因此要將其轉換至 NAS 上的獨立共用資料夾:

  • 空間預估陷阱: 主控台預估需 34.4 GB(全盤容量),但實際轉換僅寫入實體資料,儲存池峰值僅增加 5.81 GB,完成後目的資料夾佔用 3.57 GiB。
  • 高可用性表現: 轉換歷時 187 秒,期間每秒發送 ICMP 封包,連線中斷時間為 0 秒。
  • 客體狀態: 轉換完成後 canary.sh 驗證還原點不變,客體無需重開機。

維運隱患:

  1. 此 VM 落地於 NAS 的 Virtualization Station,不受 PVE HA 機制保護。
  2. 轉換後的 VM 在 Virtualization Station 預設為「自動啟動」,一旦 NAS 重開,它會開機並搶佔正式 VM 的 IP!演練驗證完畢必須立刻刪除。
  3. HDP 介面無法直接刪除轉為永久的 VM,需至 Virtualization Station 刪除,且其虛擬磁碟檔案會殘留在共用資料夾內,需手動清理。

演練 3:完整還原回 PVE 叢集(挖掘致命依賴)

選取最新備份版本,直接還原為 PVE 叢集上的新虛擬機,磁碟指回 NFS 儲存。

還原精靈設定避坑:

  • 還原模式: 預設為「覆蓋原機」,演練時請務必手動切換為「以新名稱建立」。
  • MAC 位址: 預設會產生新 MAC,導致客體內部網卡名稱跑號、靜態 IP 失效,必須手動改為「沿用原 MAC」。
  • 開機設定: 預設為「不開機」,若未勾選開機,量測出的 RTO 就會包含「等待管理員手動開機」的人為延誤。
[+23s]  VM 建立於叢集,HDP 指派新 VMID 104
[+555s] 32 GB 資料完整寫回 NFS 完畢
[+557s] VM 進入 running 狀態
[+568s] 通訊恢復(ping 通、22 埠開放)
[+569s] canary.sh 驗證通過,RTO 569 秒,RPO 784 秒

NFS 寫入吞吐量約為 64 MB/s(32 GiB 耗時 535 秒),遠慢於備份讀取時的 107 MB/s。據此推算,488 GB 的正式 VM 完整還原至少需要 2.1 小時。

發現 Cloud-Init 磁碟跨 VM 依賴陷阱
檢查還原出來的 VM 104 設定時發現:其 Cloud-Init 光碟磁碟機,竟然依然指向原 VM 920 的 vm-920-cloudinit.qcow2!
如果在真正的災難中原 VM 磁碟已毀,或演練後管理者直接刪除原 VM,這台還原出來的虛擬機就會遺失開機磁碟。
更危險的是:若你在新 VM 上點擊「移除該光碟」,PVE 會直接把底層檔案刪掉,也就是直接把原 VM 的 Cloud-Init 磁碟幹掉!
處置SOP: 還原完成後,必須立刻執行 qm cloudinit update <新VMID> 重新生成獨立設定檔,嚴禁直接移除。


演練 4:還原最舊的「不可變鎖定」版本

選取 Ver 1(首次完整備份,底層鎖定至30天後),驗證不可變限制是否會阻礙還原作業:

  • RTO 表現: 530 秒,與演練 3 的 569 秒相當,證實 WORM 鎖定狀態對讀取與還原效能零負面影響。
  • RPO 驗證: 4,104 秒,精確還原至 14:49:01Z。此數值恰好比演練 3 增加了 3,320 秒,完美吻合兩次備份的時間差。

這證明了不可變備份在面臨勒索軟體全盤毀損時,確實能提供可信賴的時光回溯能力。

驗證機制的穩定性考驗

雖然 Ver 1、Ver 2 的自動開機影片驗證成功(耗時約 144 秒),但 Ver 3、Ver 4 卻在 4 秒內閃退失敗,報錯 Virtualization Station is not responding(但同一時間 VS 運作完全正常)。這再次印證:稽核不能單看「功能有開」,必須逐次檢視驗證結果,警惕無影片存證的空白版本。


七、演練即變更,證據進軌跡

每一次的還原演練,本質上都是對生產環境或共享儲存的高負載寫入,必須視同正式變更作業(符合 Day 26 規範):

  1. 嚴禁隨手實施: 演練會在叢集佔用龐大 IOPS、消耗 NAS 空間、並產生 MAC/IP 衝突風險。
  2. 三項核心資產歸檔:
    • drill-log.md 的演練數據記錄。
    • drills.jsonl 的機器可讀自動化結果。
    • NAS 內 HDP 的開機驗證影片路徑與 Task ID。
  3. 對齊審計要求: 將上述資料與 Bareos 底層日誌勾稽,形成 Day 27 的完整合規證據鏈。

怎麼跑:演練自動化實施指南

1. 受保護客體端初始化

在每台受保護的 VM 內部署金絲雀監控腳本:

git clone https://github.com/ivanusto/pve-backup-drill && cd pve-backup-drill
sudo ./canary.sh install

2. 控制端發動演練觀測

關閉原 VM 同時,在控制端啟動自動化量測腳本。

  • 若為完整還原至 PVE 叢集(VMID 填 auto,透過 --name 比對新機名稱):
    ./restore-drill.sh auto 192.168.10.50 \
      --name debian-drill-recovered \
      --label "3. 完整還原" \
      --failed-at 2026-10-02T03:10:00Z
    
  • 若為即時還原至 Virtualization Station(加上 --no-pve 略過 PVE 狀態檢查):
    ./restore-drill.sh vs 192.168.10.50 \
      --no-pve \
      --label "1. 即時還原" \
      --failed-at 2026-10-02T03:10:00Z
    

退出碼定義: 0 代表成功驗證無誤,2 代表 Payload SHA256 校驗失敗(資料受損),3 代表連線逾時。


明天預告

Day 17 焦點拉回 儲存設備 本身。

今天的備份儲存庫、Day 13 的 AI 模型庫、以及 Day 8 建立的所有容器持久化卷,全都依託在同一台 NAS 上。當這台 NAS 本身遭遇浩劫時該如何應對? 將剖析 QuTS hero 的快照機制、HBS 3 的排程策略,並動手執行 NAS 端的 3-2-1 還原演練計時。


相關資源與索引

參考文獻


上一篇
Day 15|Proxmox VE 雙節點 HA:Virtualization Station 上的 QDevice
系列文
地端機房的三十天維運:開源服務封裝、GPU 節點守護與可稽核的變更管理 共 16 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言